package com.novoda.runbuddy.controller;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import android.graphics.BitmapFactory;
import android.location.Location;
import android.location.LocationManager;
import android.os.Handler;
import android.view.KeyEvent;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.Spinner;

import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.GeoPoint;
import com.novoda.runbuddy.R;
import com.novoda.runbuddy.activity.MapOfRuns;
import com.novoda.runbuddy.model.Run;
import com.novoda.runbuddy.model.ListOfRuns;
import com.novoda.runbuddy.util.DBHelperImpl;
import com.novoda.runbuddy.util.IDBHelper;
import com.novoda.runbuddy.view.MapOfRunsView;
import com.novoda.runbuddy.view.overlay.MapOfJogsOverlay;

public class MapOfRunsControllerImpl implements IMapOfRunsController {
// OverlayController has gone
//
	public MapOfRunsView		mapOfRunView;
	private MapController		mapViewController;
	private MapOfRuns			mapOfRunActivity;
	private Spinner				pointCollectionList;
	private MyLocationOverlay	overlayController;
	public Location				currentGPSLocationOfPhone	= null;
	protected LocationManager	locationManager				= null;
	protected IDBHelper			dbHelper;
	public ListOfRuns			listOfRuns;
	final Handler				mHandler;

	protected List<Location>	path						= new ArrayList<Location>();

	private String[][]			locations					= { { "Tullis", "-4.229920, 55.846809" },
			{ "Glasgow Green", "-4.232676, 55.846904" }	};
	private MapOfJogsOverlay	googleMapOverlay;

	public MapOfRunsControllerImpl(MapOfRuns mapOfRun) {
		this.mapOfRunActivity = mapOfRun;
		this.mHandler = new Handler();
		this.dbHelper = new DBHelperImpl(mapOfRun);
	}

	public void createMapOfRunView(MapView mapView, Spinner pointCollection, int spinnerDropDownItems, Button goButton, int day,
			int month, int year) {
		this.mapOfRunView = new MapOfRunsView(mapOfRunActivity, this, goButton, mapView);
		this.pointCollectionList = pointCollection;
		this.mapViewController = mapView.getController();
		this.listOfRuns = dbHelper.fetchAllJogEntries(day, month, year);

		locations = listOfRuns.toArray();

		setSpinnerPresenter(populateSpinnerListPresenter(mapOfRunActivity, spinnerDropDownItems, locations));

//		this.overlayController = mapView.createOverlayController();

		this.googleMapOverlay = new MapOfJogsOverlay(this.mapOfRunActivity, BitmapFactory.decodeResource(this.mapOfRunActivity
				.getResources(), R.drawable.map_start_point), BitmapFactory.decodeResource(this.mapOfRunActivity.getResources(),
				R.drawable.map_stop_point), BitmapFactory.decodeResource(this.mapOfRunActivity.getResources(), R.drawable.dial));

//		overlayController.add(googleMapOverlay, true);

		centerTheScreenOnTheLastRunRoute();

	}

	private void centerTheScreenOnTheLastRunRoute() {
		Location pointLocation = new Location("location");
		pointLocation.setLatitude(55.846904);
		pointLocation.setLongitude(-4.232676);
		setCurrentGPSLocationOfPhone(pointLocation);
		gotoCurrentGPSPosition();
	}

	public void plotChosenRun() {
		drawCurrentlySelectedRunPath();
		// gotoCurrentlySelected();
	}

	private void drawCurrentlySelectedRunPath() {
		this.googleMapOverlay.path.clear();
		path.clear();
		Run run = listOfRuns.get(this.pointCollectionList.getSelectedItemPosition());
		Map<Long, Location> locationsAndTimes = run.getlocationsAndTimes();

		for (Iterator<Map.Entry<Long, Location>> it = locationsAndTimes.entrySet().iterator(); it.hasNext();) {
			Map.Entry<Long, Location> entry = (Map.Entry<Long, Location>) it.next();
			Location location = entry.getValue();
			addPoint(location);
			setCurrentGPSLocationOfPhone(location);
		}

		gotoCurrentGPSPosition2();

	}

	private ArrayAdapter<CharSequence> populateSpinnerListPresenter(MapActivity mapOfJogActivity, int spinnerDropDownListID,
			String[][] locations) {
		ArrayAdapter<CharSequence> adapter = new ArrayAdapter<CharSequence>(mapOfJogActivity, spinnerDropDownListID);

		for (int i = 0; i < locations.length; i++) {
			adapter.add(locations[i][0]);
		}

		adapter.setDropDownViewResource(spinnerDropDownListID);
		return adapter;
	}

	private void setSpinnerPresenter(ArrayAdapter<CharSequence> adapter) {
		this.pointCollectionList.setAdapter(adapter);
	}

	public void gotoCurrentlySelected() {
		Location mapPoint = getMapPointFromLocationList(this.pointCollectionList.getSelectedItemPosition());

		setCurrentGPSLocationOfPhone(mapPoint);
		gotoCurrentGPSPosition();
	}

	public void gotoCurrentGPSPosition() {

		GeoPoint point = new GeoPoint((int) (this.currentGPSLocationOfPhone.getLatitude() * 1000000),
				(int) (this.currentGPSLocationOfPhone.getLongitude() * 1000000));

		mapViewController.animateTo(point);
		mapViewController.setZoom(18);
		mapOfRunView.invalidateMapView();

	}

	public void gotoCurrentGPSPosition2() {

		GeoPoint point = new GeoPoint((int) (this.currentGPSLocationOfPhone.getLatitude()), (int) (this.currentGPSLocationOfPhone
				.getLongitude()));

		mapViewController.animateTo(point);
		mapViewController.setZoom(18);
		mapOfRunView.invalidateMapView();

	}

	private Location getMapPointFromLocationList(int pos) {
		String[] loc = locations[pos][1].split(",");

		double lat = Double.parseDouble(loc[1]);
		double lon = Double.parseDouble(loc[0]);

		Location pointLocation = new Location("location");
		pointLocation.setLatitude(lat);
		pointLocation.setLongitude(lon);

		return pointLocation;
	}

	public void zoomTo(int zoomLevel) {
		this.mapViewController.setZoom(zoomLevel);
	}

	public boolean onKeyDown(int keyCode, KeyEvent event) {

		switch (keyCode) {
			case KeyEvent.KEYCODE_I:
				mapViewController.setZoom(mapOfRunView.getZoomLevel() + 1);
				break;
			case KeyEvent.KEYCODE_O:
				mapViewController.setZoom(mapOfRunView.getZoomLevel() - 1);
				break;
			case KeyEvent.KEYCODE_V:
				draw1Point();
				break;
			case KeyEvent.KEYCODE_B:
				draw2Point();
				break;
			case KeyEvent.KEYCODE_N:
				draw3Point();
				break;
			case KeyEvent.KEYCODE_M:
				draw4Point();
				break;
			case KeyEvent.KEYCODE_L:
				this.googleMapOverlay.path.clear();
				drawPoints();
				break;
			case KeyEvent.KEYCODE_P:
				this.googleMapOverlay.path.clear();
				drawPoints2();
				break;
			case KeyEvent.KEYCODE_Q:
				this.googleMapOverlay.path.clear();
				drawPathFromDB2();
				break;
			case KeyEvent.KEYCODE_S:
				mapOfRunView.toggleSatellite();
				break;
			case KeyEvent.KEYCODE_BACK:
//				this.overlayController.deactivate(this.googleMapOverlay);
		}

		return true;
	}

	private void drawPathFromDB2() {
		path.clear();
		Run run = listOfRuns.getLast();
		Map<Long, Location> locationsAndTimes = run.getlocationsAndTimes();

		for (Iterator<Map.Entry<Long, Location>> it = locationsAndTimes.entrySet().iterator(); it.hasNext();) {
			Map.Entry<Long, Location> entry = (Map.Entry<Long, Location>) it.next();
			Location location = entry.getValue();
			addPoint(location);
			setCurrentGPSLocationOfPhone(location);
		}

		gotoCurrentGPSPosition2();

	}

	public void draw1Point() {
		addPoint(55846809, -4229920);
	}

	public void draw2Point() {
		addPoint(55846809, -4231200);
	}

	public void draw3Point() {
		addPoint(55851200, -4236400);
	}

	public void draw4Point() {
		addPoint(55851000, -4236800);
	}

	private boolean addPoint(double latitude, double longitude) {
		Location pointLocation = new Location("location");
		pointLocation.setLatitude(latitude);
		pointLocation.setLongitude(longitude);
		this.googleMapOverlay.addLocationToPath(pointLocation);
		mapOfRunView.invalidateMapView();
		return true;
	}

	private boolean addPoint(Location location) {
		this.googleMapOverlay.addLocationToPath(location);
		mapOfRunView.invalidateMapView();
		return true;
	}

	public void drawPoints() {
		path.clear();
		draw1Point();
		draw2Point();
		draw3Point();
		draw4Point();
	}

	public void drawPoints2() {
		path.clear();
		draw2Point();
		draw4Point();
		draw1Point();
		draw3Point();
	}

	public void updateRunningPath() {
		if (this.currentGPSLocationOfPhone != null) {
			Location pointLocation = new Location("location");
			pointLocation.setLatitude(this.currentGPSLocationOfPhone.getLatitude() * 1000000);
			pointLocation.setLongitude(this.currentGPSLocationOfPhone.getLongitude() * 1000000);
			this.googleMapOverlay.addLocationToPath(pointLocation);
			gotoCurrentGPSPosition();
		}
	}

	public void setCurrentGPSLocationOfPhone(Location currentLocation) {
		this.currentGPSLocationOfPhone = currentLocation;
	}

}
